package com.sunwayworld.basemodule.common.asynctask.resource.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sunwayworld.basemodule.common.asynctask.bean.LimsAsynctaskBean;
import com.sunwayworld.basemodule.common.asynctask.bean.LimsAsynctaskInsert;
import com.sunwayworld.basemodule.common.asynctask.bean.LimsAsynctaskScheduleBean;
import com.sunwayworld.basemodule.common.asynctask.bean.LimsAsynctaskServerBean;
import com.sunwayworld.basemodule.common.asynctask.config.AsyncTaskExecutorConfig;
import com.sunwayworld.basemodule.common.asynctask.resource.LimsAsynctaskResource;
import com.sunwayworld.basemodule.common.asynctask.service.LimsAsynctaskScheduleService;
import com.sunwayworld.basemodule.common.asynctask.service.LimsAsynctaskService;
import com.sunwayworld.basemodule.common.asynctask.statics.TaskStaticsInfo;
import com.sunwayworld.basemodule.common.asynctask.statics.TaskTypeExecuteInfo;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.context.LocalContextHelper;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.log.annotation.Log;
import com.sunwayworld.framework.log.annotation.LogModule;
import com.sunwayworld.framework.log.annotation.LogType;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.utils.ClassUtils;
import com.sunwayworld.framework.utils.ObjectUtils;
import com.sunwayworld.framework.utils.ReflectionUtils;
import com.sunwayworld.framework.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@LogModule("异步任务")
@RestController
@GikamBean
public class LimsAsynctaskResourceImpl implements LimsAsynctaskResource {

    @Autowired
    private LimsAsynctaskService limsAsynctaskService;
    @Autowired
    private AsyncTaskExecutorConfig asyncTaskExecutorConfig;
    @Autowired
    private LimsAsynctaskScheduleService limsAsynctaskScheduleService;

    @Override
    public LimsAsynctaskService getService() {
        return limsAsynctaskService;
    }

    @Log(value = "新增异步任务", type = LogType.INSERT)
    @Override
    @RequestMapping(method = RequestMethod.POST)
    public Long insert(RestJsonWrapperBean wrapper) {
        return getService().insert(wrapper);
    }


    @Override
    public Map<String,Object> addTask(RestJsonWrapperBean wrapperBean) {
        List<LimsAsynctaskInsert> inserts = wrapperBean.parse(LimsAsynctaskInsert.class);
        for (LimsAsynctaskInsert insert : inserts) {
            if(insert.getTaskId()==null){
                throw new InvalidDataException("任务ID不能为空！");
            }
            if(ObjectUtils.isEmpty(insert.getTaskName())){
                throw new InvalidDataException("任务名称不能为空！");
            }
            if(ObjectUtils.isEmpty(insert.getTaskType())){
                throw new InvalidDataException("任务类型不能为空！");
            }
            if(ObjectUtils.isEmpty(insert.getExecutorName())){
                throw new InvalidDataException("任务执行器名称不能为空！");
            }
            List<LimsAsynctaskScheduleBean> limsAsynctaskScheduleBeans = limsAsynctaskScheduleService.selectAll();
            if(ObjectUtils.isEmpty(limsAsynctaskScheduleBeans)){
                throw new InvalidDataException("未配置异步任务线程池！");
            }
            boolean present = limsAsynctaskScheduleBeans.stream().filter(c -> insert.getExecutorName().equals(c.getExecutorId())).findFirst().isPresent();
            if(!present){
                List<String> list = limsAsynctaskScheduleBeans.stream().map(f -> f.getExecutorId()).distinct().collect(Collectors.toList());
                throw new InvalidDataException("任务执行器不存在，只能输入下面这些执行器:"+ StringUtils.join(list,","));
            }
            if(!ObjectUtils.isEmpty(insert.getJsonParam())){
                try {
                    JSON.parseObject(insert.getJsonParam());
                }catch (Throwable s){
                    s.printStackTrace();
                    throw new InvalidDataException("请输入JSON格式的参数！");
                }
            }
            if(ObjectUtils.isEmpty(insert.getServiceMethod())){
                throw new InvalidDataException("调用方法不能为空！");
            }
            int index = insert.getServiceMethod().lastIndexOf(".");
            if(index==-1){
                throw new InvalidDataException("请输入调用方法的全路径！");
            }
            String serviceName = insert.getServiceMethod().substring(0, index);
            String methodName = insert.getServiceMethod().substring(index + 1);
            Class<?> serviceClazz = null;
            try {
                serviceClazz = ClassUtils.getClass(serviceName);
            }catch (Throwable s){
                s.printStackTrace();
            }
            if(serviceClazz==null){
                throw new InvalidDataException("调用class不存在！");
            }
            Object service = ApplicationContextHelper.getBean(serviceClazz);
            if(service==null){
                throw new InvalidDataException("调用service未注入！");
            }
            Method method = null;
            if(!ObjectUtils.isEmpty(insert.getJsonParam())){
                //methodName 如果有参数，参数必须RestJsonWrapperBean
                method = ReflectionUtils.findMethod(serviceClazz, methodName, new Class[]{JSONObject.class});
            }else{
                method = ReflectionUtils.findMethod(serviceClazz, methodName);
            }
            if(method==null){
                throw new InvalidDataException("调用方法不存在！");
            }
        }
        return getService().addAsyncTask(inserts, LocalContextHelper.getLoginUser());
    }

    @Override
    public Map<String,Object> testTask(RestJsonWrapperBean wrapperBean) {
        return getService().testTask(wrapperBean.parse(LimsAsynctaskBean.class));
    }

    @Override
    public TaskStaticsInfo queryTaskStaticsInfo() {
        return getService().queryTaskStaticsInfo();
    }

    @Override
    public TaskTypeExecuteInfo queryTaskTypeExecuteInfo() {
        return getService().queryTaskTypeExecuteInfo();
    }

    @Override
    public List<LimsAsynctaskServerBean> asyncServerHealth() {
        return getService().asyncServerHealth();
    }

}
